

package ar.com.photo_admin.service

import javax.annotation.PostConstruct;

import ar.com.photo_admin.domain.*;
import grails.converters.*;
import groovy.json.JsonSlurper

import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.*;


class PayingService extends BaseService {
	
	def purchaseOrderService
	def notificationsService
	def shoppingCartService
	def appDomainUrl
	HttpClient httpclient = new HttpClient();
	
	

	def CLIENT_ID = "623938634179880" // tpfiuba "4506497372934265"; 
	def CLIENT_SECRET = "GkqeeLS8xpoqaRXps0q2HpEzZ5loxf6X" //tpfiuba "82Pg9UJyLdbSGNcXATxR9HxiCcsxnu2y";
	
		
	
	@PostConstruct
	def initService(){
		appDomainUrl = grailsApplication.config.app.domain.url;
		
	}
	
	//ARMADO DE LA ORDEN	
	def createPreference(purchaseOrder,clientId,clientSecret){
		def checkoutUrl =""
		try{
			def accessToken = getAccessToken(clientId,clientSecret)
			log.info "Armando el pedido"
			def bodyMap = creatingMPOrder(purchaseOrder)
			checkoutUrl = createPreferenceRequest(accessToken,bodyMap)
			log.info "Ha finalizado el armado del pedido \n\n";
		}	
		catch(java.net.UnknownHostException e){
			log.error "No se puede conectar a Mercado Pago."			
		}
				
		return checkoutUrl;
	}
	
	def createPreferenceRequest(accessToken,bodyMap){
		def initPoint = null;			
		PostMethod post = new PostMethod("https://api.mercadolibre.com/checkout/preferences?access_token=${accessToken}");
		post.addRequestHeader("Accept","application/json");
		post.addRequestHeader("Content-Type", "application/json");
		
		fillBodyJSONMessage(post,bodyMap)
		
		int code = httpclient.executeMethod(post);
		log.info "Response status code: " + code;
		def respJson2 = new JsonSlurper().parseText( post.getResponseBodyAsString() )
		log.info "Init point a mercado pago"+ respJson2.init_point;
		initPoint =  respJson2.init_point;			
		
		return initPoint;
	}
	
	
	
	// Registra las notificaciones automaticas emitidas por Mercado Pago cuando se produce un cambio
	// en el estado de una orden.
	def registerNotification(notifId,clientId,clientSecret){
		PostMethod post = null
		try{
			log.info "Se pregunta que informacion tiene la notificacion ${notifId}";
			def accessToken = getAccessToken(clientId,clientSecret)
	
			post = new PostMethod("https://api.mercadolibre.com/collections/notifications/${notifId}?access_token=${accessToken}");
			post.addRequestHeader("Accept","application/json");
			int code = httpclient.executeMethod(post);
			log.info "Codigo de respuesta " + code;
			def respJson = new JsonSlurper().parseText( post.getResponseBodyAsString() )
			def orderNotif = respJson.collection
			log.info "Descripcion "+ orderNotif;
			log.info "Id del pago recibido: "+ orderNotif.id;
			log.info "Estado del pago recibido: "+ orderNotif.status;
			log.info "External reference: "+ orderNotif.external_reference;
			
			PurchaseOrder order = PurchaseOrder.get(orderNotif.external_reference)
			if (order != null){
										
				boolean newOrder = !order.isRegistered()
				if(newOrder){					
					log.info "New order"
					order.MPpaymentId = orderNotif.id
					order.paidOnline = true;
					purchaseOrderService.completeConfirmation(order)
					shoppingCartService.emptyShoppingCartForUser(order.client,order.photographer)
				}
				order.updateStatusFromMPStringStatus(orderNotif.status);
				//order = order.merge()
				order.save(flush:true);
				
				//Realiza las notificaciones correspondientes
				notificationsService.notifyOrderStatusChange(order);
			}
			
			log.info "Se avisa a MP que la notificacion fue registrada correctamente \n\n";
		}
		catch(Exception e){
			log.error "No se pudo procesar la notificacion"
			log.error "Stacktrace: ${e.message}"
		}
		finally{
			if( post != null)
				post.releaseConnection()
		}
				
	}
	
	
	
	// CANCELACION
	def cancelOrRefundOrder(paymentId,isCancel,clientId,clientSecret){				
		def accessToken = getAccessToken(clientId,clientSecret)		
		def put= new PutMethod("https://api.mercadolibre.com/collections/${paymentId}?access_token=${accessToken}");
		put.addRequestHeader("Content-Type", "application/json");	
		
		//TODO por alguna razon tiene que cancelarlo?
		//def desiredStatus = isCancel ? 'cancelled' : 'refunded' 	
		def desiredStatus = 'cancelled' 
		def body = [:];
		body.status = desiredStatus
		
		def bodyAsJSON = (String) body as JSON				
		RequestEntity requestEntity = new StringRequestEntity(bodyAsJSON, "application/json", "UTF-8")
		put.setRequestEntity(requestEntity);
		
		int code = httpclient.executeMethod(put);
		log.info "Codigo de respuesta " + code;
		log.info "Ha finalizado la cancelacion o devolución del pedido \n\n";
		return code == 200			
	}
	
	
	
	
	
	def fillBodyJSONMessage(method,bodyMap){
		def bodyAsJSON = (String) bodyMap as JSON		
		RequestEntity requestEntity = new StringRequestEntity(bodyAsJSON, "application/json", "UTF-8")
		method.setRequestEntity(requestEntity);
	}
	

	
	def creatingMPOrder(purchaseOrder){

		
		//Armo los urls del pedido		
		def g = grailsApplication.mainContext.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
		def pageUrl = appDomainUrl + g.createLink(controller: 'purchaseOrder', action: 'show', id: purchaseOrder.id)
		
		def backUrls = [:]
		backUrls.success = pageUrl;
		//backUrls.failure = pageUrl;
		backUrls.pending = pageUrl;        				
		
		def pedido = [:];		
		// Preparo se ejecuta el pedido JSON
		def description = [:];
		description['title'] = "Copias: ${purchaseOrder.amountCopies}";
		description['quantity'] =  1 ;
		description['currency_id'] = 'ARS';
		description['unit_price'] = purchaseOrder.price;				
		
		pedido['items'] = [ description ];
		pedido['external_reference'] = (new Long(purchaseOrder.id)).toString()
		pedido['back_urls'] = backUrls;
				
		log.info "Backurls: "+ backUrls		
		log.info "Descripcion del pedido: " + pedido
		log.info "El precio de la orden emitida es "+purchaseOrder.price
		log.info "La pagina a donde se dirigira luego es " + pageUrl
		return pedido
	}
	
	def respondOk(resultCode){
		
	}
	
	def getAccessToken(clientId,clientSecret){
		log.info "Buscando el access token";
		
		PostMethod post = null;		
		
		post = new PostMethod("https://api.mercadolibre.com/oauth/token");
		post.addRequestHeader("Accept","application/json");
		post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		post.addParameter("grant_type","client_credentials");
		post.addParameter("client_id",clientId);
		post.addParameter("client_secret",clientSecret);		
		int result = httpclient.executeMethod(post);
		def respJson = new JsonSlurper().parseText( post.getResponseBodyAsString() )
		log.info "AccessToken de Mercado pago:"+ respJson.access_token;		
				
		return  respJson.access_token;
		
	}

}
